Ext.Container = Ext.extend(Ext.BoxComponent,
{
	autoDestroy: true,
	forceLayout: false,
	defaultType: 'panel',
	resizeEvent: 'resize',
	bubbleEvents:
	[
	    'add', 'remove'
	],

	// private
	initComponent: function()
	{
		Ext.Container.superclass.initComponent.call(this);

		this.addEvents('afterlayout', 'beforeadd', 'beforeremove', 'add', 'remove');

		var items = this.items;
		if( items )
		{

			// 将this.items删除
			delete this.items;

			// 解析形如items:[{html:'abc'},{html:'def'}]....
			// 将嵌套的items一个一个的解析出来
			this.add(items);
		}
	},

	initItems: function()
	{
		if( !this.items )
		{
			this.items = new Ext.util.MixedCollection(false, this.getComponentId);
			this.getLayout(); // 初始化layout
		}
	},

	setLayout: function( layout )
	{
		if( this.layout && this.layout != layout )
		{
			this.layout.setContainer(null);
		}
		this.layout = layout;
		this.initItems();
		// 设置layout的container
		layout.setContainer(this);
	},

	afterRender: function()
	{
		// Render this Container, this should be done before setLayout is called which
		// will hook onResize
		Ext.Container.superclass.afterRender.call(this);
		if( !this.layout )
		{
			this.layout = 'auto';
		}
		if( Ext.isObject(this.layout) && !this.layout.layout ) // this.layout.layout检测是否有layout方法
		{
			this.layoutConfig = this.layout;
			this.layout = this.layoutConfig.type;
		}
		if( Ext.isString(this.layout) )
		{
			this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
		}
		this.setLayout(this.layout);

		// If a CardLayout, the active item set
		if( this.activeItem !== undefined && this.layout.setActiveItem ) // 只有布局是CardLayout的时候，才有用，稍后分析！
		{
			var item = this.activeItem;
			delete this.activeItem;
			this.layout.setActiveItem(item);
		}

		// If we have no ownerCt, render and size all children
		if( !this.ownerCt ) // 如果没有ownerCt，则表示还没有渲染
		{
			this.doLayout(false, true);
		}

		// This is a manually configured flag set by users in conjunction with renderTo.
		// Not to be confused with the flag by the same name used in Layouts.
		if( this.monitorResize === true )
		{
			Ext.EventManager.onWindowResize(this.doLayout, this,
			[
				false
			]);
		}
	},

	getLayoutTarget: function()
	{
		return this.el;
	},

	// private - used as the key lookup function for the items collection
	getComponentId: function( comp )
	{
		return comp.getItemId();
	},

	add: function( comp )
	{
		this.initItems();
		var args = arguments.length > 1;

		// 如果参数大于1，或者是个数组，那么就遍历args或者数组，将获取的items中的项push到result中
		// 这其中是一个递归的过程，主要的方法是lookupComponent
		if( args || Ext.isArray(comp) )
		{
			var result = [];
			Ext.each(args ? arguments : comp, function( c )
			{
				result.push(this.add(c));
			}, this);
			return result;
		}
		var c = this.lookupComponent(this.applyDefaults(comp));
		var index = this.items.length;
		if( this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false )
		{
			this.items.add(c);
			// *onAdded
			c.onAdded(this, index);
			this.onAdd(c);
			this.fireEvent('add', this, c, index);
		}
		return c;
	},

	onAdd: function( c )
	{
		// Empty template method
	},

	// private
	onAdded: function( container, pos )
	{
		// overridden here so we can cascade down, not worth creating a template method.
		this.ownerCt = container;
		this.initRef();
		// initialize references for child items
		this.cascade(function( c )
		{
			c.initRef();
		});
		this.fireEvent('added', this, container, pos);
	},

	insert: function( index, comp )
	{
		var args = arguments, length = args.length, result = [], i, c;

		this.initItems();

		if( length > 2 )
		{
			for( i = length - 1; i >= 1; --i )
			{
				result.push(this.insert(index, args[i]));
			}
			return result;
		}

		c = this.lookupComponent(this.applyDefaults(comp));
		index = Math.min(index, this.items.length);

		if( this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false )
		{
			if( c.ownerCt == this )
			{
				this.items.remove(c);
			}
			this.items.insert(index, c);
			c.onAdded(this, index);
			this.onAdd(c);
			this.fireEvent('add', this, c, index);
		}

		return c;
	},

	// private
	applyDefaults: function( c )
	{
		var d = this.defaults;
		if( d )
		{
			if( Ext.isFunction(d) )
			{
				d = d.call(this, c);
			}
			if( Ext.isString(c) )
			{
				c = Ext.ComponentMgr.get(c);
				Ext.apply(c, d);
			}
			else if( !c.events )
			{
				Ext.applyIf(c.isAction ? c.initialConfig : c, d);
			}
			else
			{
				Ext.apply(c, d);
			}
		}
		return c;
	},

	// private
	onBeforeAdd: function( item )
	{
		if( item.ownerCt )
		{
			item.ownerCt.remove(item, false);
		}
		if( this.hideBorders === true )
		{
			item.border = (item.border === true);
		}
	},

	remove: function( comp, autoDestroy )
	{
		this.initItems();
		var c = this.getComponent(comp);
		if( c && this.fireEvent('beforeremove', this, c) !== false )
		{
			this.doRemove(c, autoDestroy);
			this.fireEvent('remove', this, c);
		}
		return c;
	},

	onRemove: function( c )
	{
		// Empty template method
	},

	// private
	doRemove: function( c, autoDestroy )
	{
		var l = this.layout, hasLayout = l && this.rendered;

		if( hasLayout )
		{
			l.onRemove(c);
		}
		this.items.remove(c);
		c.onRemoved();
		this.onRemove(c);
		if( autoDestroy === true || (autoDestroy !== false && this.autoDestroy) )
		{
			c.destroy();
		}
		if( hasLayout )
		{
			l.afterRemove(c);
		}
	},

	removeAll: function( autoDestroy )
	{
		this.initItems();
		var item, rem = [], items = [];
		this.items.each(function( i )
		{
			rem.push(i);
		});
		for( var i = 0, len = rem.length; i < len; ++i )
		{
			item = rem[i];
			this.remove(item, autoDestroy);
			if( item.ownerCt !== this )
			{
				items.push(item);
			}
		}
		return items;
	},

	getComponent: function( comp )
	{
		if( Ext.isObject(comp) )
		{
			comp = comp.getItemId();
		}
		return this.items.get(comp);
	},

	// private
	lookupComponent: function( comp )
	{

		// 如果是字符串，那么用compontManger来查找
		if( Ext.isString(comp) )
		{
			return Ext.ComponentMgr.get(comp);

			// 如果是events对象，说明已经初始化完毕，直接返回
			// 如果不是，则调用createComponent
		}
		else if( !comp.events )
		{
			return this.createComponent(comp);
		}
		return comp;
	},

	// private
	createComponent: function( config, defaultType )
	{

		// 若是config有render属性，则直接返回
		if( config.render )
		{
			return config;
		}
		// add in ownerCt at creation time but then immediately
		// remove so that onBeforeAdd can handle it

		// 如果没有defaultType，则类型为panel
		var c = Ext.create(Ext.apply(
		{
			ownerCt: this
		}, config), defaultType || this.defaultType); // panel

		/**
		 * var c = Ext.create(Ext.apply({ownerCt:this,html:'AAA'},'panel'));
		 */
		delete c.initialConfig.ownerCt;
		delete c.ownerCt;
		return c;
	},

	canLayout: function()
	{
		var el = this.getVisibilityEl();
		return el && el.dom && !el.isStyle("display", "none");
	},

	doLayout: function( shallow, force )
	{
		var rendered = this.rendered, forceLayout = force || this.forceLayout;

		if( this.collapsed || !this.canLayout() ) // 这里应该是bordLayout的专属么？？？
		{
			this.deferLayout = this.deferLayout || !shallow;
			if( !forceLayout )
			{
				return;
			}
			shallow = shallow && !this.deferLayout;
		}
		else
		{
			delete this.deferLayout;
		}

		if( rendered && this.layout )
		{
			this.layout.layout(); // 此处转到layout的实现类里去执行了
			// ContainerLayout 为何是它 ？
		}
		if( shallow !== true && this.items )
		{
			var cs = this.items.items;
			for( var i = 0, len = cs.length; i < len; i++ )
			{
				var c = cs[i];
				if( c.doLayout )
				{
					c.doLayout(false, forceLayout);
				}
			}
		}
		if( rendered )
		{
			this.onLayout(shallow, forceLayout);
		}
		// Initial layout completed
		this.hasLayout = true;
		delete this.forceLayout;
	},

	onLayout: Ext.emptyFn,

	// private
	shouldBufferLayout: function()
	{
		/*
		 * Returns true if the container should buffer a layout. This is true only if the container has previously been laid out and has a parent container that is
		 * pending a layout.
		 */
		var hl = this.hasLayout;
		if( this.ownerCt )
		{
			// Only ever buffer if we've laid out the first time and we have one pending.
			return hl ? !this.hasLayoutPending() : false;
		}
		// Never buffer initial layout
		return hl;
	},

	// private
	hasLayoutPending: function()
	{
		// Traverse hierarchy to see if any parent container has a pending layout.
		var pending = false;
		this.ownerCt.bubble(function( c )
		{
			if( c.layoutPending )
			{
				pending = true;
				return false;
			}
		});
		return pending;
	},

	onShow: function()
	{
		// removes css classes that were added to hide
		Ext.Container.superclass.onShow.call(this);
		// If we were sized during the time we were hidden, layout.
		if( Ext.isDefined(this.deferLayout) )
		{
			delete this.deferLayout;
			this.doLayout(true);
		}
	},

	getLayout: function()
	{
		if( !this.layout )
		{

			// 如果没有设置layout配置项，那么就将autoLayout设置为其layout
			var layout = new Ext.layout.AutoLayout(this.layoutConfig);
			this.setLayout(layout);
		}
		return this.layout;
	},

	// private
	beforeDestroy: function()
	{
		var c;
		if( this.items )
		{
			while(c = this.items.first())
			{
				this.doRemove(c, true);
			}
		}
		if( this.monitorResize )
		{
			Ext.EventManager.removeResizeListener(this.doLayout, this);
		}
		Ext.destroy(this.layout);
		Ext.Container.superclass.beforeDestroy.call(this);
	},

	cascade: function( fn, scope, args )
	{
		if( fn.apply(scope || this, args ||
		[
			this
		]) !== false )
		{
			if( this.items )
			{
				var cs = this.items.items;
				for( var i = 0, len = cs.length; i < len; i++ )
				{
					if( cs[i].cascade )
					{
						cs[i].cascade(fn, scope, args);
					}
					else
					{
						fn.apply(scope || cs[i], args ||
						[
							cs[i]
						]);
					}
				}
			}
		}
		return this;
	},

	findById: function( id )
	{
		var m = null, ct = this;
		this.cascade(function( c )
		{
			if( ct != c && c.id === id )
			{
				m = c;
				return false;
			}
		});
		return m;
	},

	findByType: function( xtype, shallow )
	{
		return this.findBy(function( c )
		{
			return c.isXType(xtype, shallow);
		});
	},

	find: function( prop, value )
	{
		return this.findBy(function( c )
		{
			return c[prop] === value;
		});
	},

	findBy: function( fn, scope )
	{
		var m = [], ct = this;
		this.cascade(function( c )
		{
			if( ct != c && fn.call(scope || c, c, ct) === true )
			{
				m.push(c);
			}
		});
		return m;
	},

	get: function( key )
	{
		return this.getComponent(key);
	}
});

Ext.Container.LAYOUTS = {};
Ext.reg('container', Ext.Container);
